package net.dopan.pigframe.auth.config;

import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import lombok.extern.slf4j.Slf4j;
import net.dopan.pigframe.auth.component.mobile.MobileSecurityConfigurer;
import net.dopan.pigframe.core.bean.config.FilterIgnorePropertiesConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;

/**
 * @Package: net.dopan.pigframe.auth.config
 * @Title: MySecurityConfigurerAdapter
 * @Description: 
 * @author: 刘宽
 * @date: 2018/9/6 16:28
 */
@Slf4j
@Order(SecurityProperties.BASIC_AUTH_ORDER - 3)
@Configuration
@EnableWebSecurity
public class MySecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

    @Autowired
    private FilterIgnorePropertiesConfig filterIgnorePropertiesConfig;

    @Autowired
    private MobileSecurityConfigurer mobileSecurityConfigurer;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry =
                http.formLogin()
                        // .loginPage("/authentication/require")
                        .loginProcessingUrl("/authentication/form")
                        .and()
                        .authorizeRequests();
                        //.antMatchers("/oauth/token").permitAll()
                        //.anyRequest().authenticated();
                //http.csrf().disable().authorizeRequests();
        log.info("AuthIgnoreUrls: {}", filterIgnorePropertiesConfig.getUrls());
        filterIgnorePropertiesConfig.getUrls().forEach(url -> registry.antMatchers(url).permitAll());
        registry.anyRequest().authenticated()
                .and()
                .cors()
                .and()
                .csrf().disable();
                //.httpBasic();
        http.apply(mobileSecurityConfigurer);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/favicon.ico");
    }

    /**
     * 认证管理
     *
     * @return 认证管理对象
     * @throws Exception
     *             认证异常信息
     */
    /**
     * (name = BeanIds.AUTHENTICATION_MANAGER)
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * 加密方式
     * https://spring.io/blog/2017/11/01/spring-security-5-0-0-rc1-released#password-storage-updated
     * Encoded password does not look like BCrypt
     *
     * @return PasswordEncoder
     */
    /*@Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }*/

    @Autowired
    private RefreshScope refreshScope;
    /**
     * apollo更新刷新filterIgnorePropertiesConfig
     * @param changeEvent
     */
    @ApolloConfigChangeListener
    public void onChange(ConfigChangeEvent changeEvent) {
        boolean ignoreCacheKeysChanged = false;
        for (String changedKey : changeEvent.changedKeys()) {
            if (changedKey.startsWith("ignore")) {
                ignoreCacheKeysChanged = true;
                break;
            }
        }
        if (!ignoreCacheKeysChanged) {
            return;
        }
        log.info("AuthIgnoreUrls before refresh {}", filterIgnorePropertiesConfig.getUrls());
        refreshScope.refresh("filterIgnorePropertiesConfig");
        log.info("AuthIgnoreUrls after refresh {}", filterIgnorePropertiesConfig.getUrls());
    }
}